package com.spsoft.vatoutinv.service.vmsdifferentialcode.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spsoft.core.enums.ResponseEnum;
import com.spsoft.core.model.Result;
import com.spsoft.core.model.bo.TokenUser;
import com.spsoft.core.model.leqidmz.param.BaseUserInfoParam;
import com.spsoft.core.model.leqidmz.response.QueryDifferentialTaxationVO;
import com.spsoft.core.utils.BeanUtils;
import com.spsoft.core.utils.SecurityUtils;
import com.spsoft.core.utils.StringUtil;
import com.spsoft.einvoicetodmz.service.DmzApiClientService;
import com.spsoft.vatoutinv.constants.CommonConstant;
import com.spsoft.vatoutinv.entity.vmsclassifycode.VmsClassifyCode;
import com.spsoft.vatoutinv.entity.vmsdifferentialcode.VmsDifferentialCode;
import com.spsoft.vatoutinv.entity.vmsdifferentialcode.VmsDifferentialCodeRInfo;
import com.spsoft.vatoutinv.entity.vmsdifferentialcode.VmsDifferentialCodeRecord;
import com.spsoft.vatoutinv.entity.vmsenterpriseinfo.VmsEnterpriseInfo;
import com.spsoft.vatoutinv.enums.CommonEnum;
import com.spsoft.vatoutinv.mapper.VmsDifferentialCodeMapper;
import com.spsoft.vatoutinv.model.dto.vmsdifferentialcode.DifferentialCodeLogListDto;
import com.spsoft.vatoutinv.model.dto.vmsdifferentialcode.DifferentialCodeLogPageDto;
import com.spsoft.vatoutinv.model.dto.vmsdifferentialcode.DifferentialCodePageDto;
import com.spsoft.vatoutinv.model.vo.vmsdifferentialcode.DifferentialCodeLogPageVo;
import com.spsoft.vatoutinv.model.vo.vmsdifferentialcode.DifferentialCodePageVo;
import com.spsoft.vatoutinv.service.vmsclassifycode.VmsClassifyCodeService;
import com.spsoft.vatoutinv.service.vmsdifferentialcode.VmsDifferentialCodeRInfoService;
import com.spsoft.vatoutinv.service.vmsdifferentialcode.VmsDifferentialCodeRecordService;
import com.spsoft.vatoutinv.service.vmsdifferentialcode.VmsDifferentialCodeService;
import com.spsoft.vatoutinv.service.vmsenterpriseinfo.VmsEnterpriseInfoService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

/**
 * @author wangy
 * @description 针对表【VMS_DIFFERENTIAL_CODE(差额征税编码信息管理)】的数据库操作Service实现
 * @createDate 2024-03-26 09:45:59
 */
@Slf4j
@Service
@RequiredArgsConstructor
@SuppressWarnings("unchecked")
public class VmsDifferentialCodeServiceImpl extends ServiceImpl<VmsDifferentialCodeMapper, VmsDifferentialCode> implements VmsDifferentialCodeService {

    public static final String LOG_MSG = "(差额征税编码信息管理实现层)";

    private final VmsDifferentialCodeRecordService differentialCodeRecordService;

    private final VmsDifferentialCodeRInfoService differentialCodeRInfoService;

    private final VmsEnterpriseInfoService vmsEnterpriseInfoService;

    private final VmsClassifyCodeService vmsClassifyCodeService;

    private final DmzApiClientService dmzApiClientService;

    @Override
    public Result<IPage<DifferentialCodePageVo>> page(DifferentialCodePageDto dto) {
        String deptCode = SecurityUtils.getDeptCode();
        Integer pageNo = dto.getPageNo();
        Integer pageSize = dto.getPageSize();

        Page<VmsDifferentialCode> page = page(new Page<>(pageNo, pageSize), new LambdaQueryWrapper<VmsDifferentialCode>()
                .eq(VmsDifferentialCode::getDeptCode, deptCode)
                .eq(StringUtil.isNotEmpty(dto.getSphfwssflhbbm()), VmsDifferentialCode::getSphfwssflhbbm, dto.getSphfwssflhbbm())
                .likeRight(StringUtil.isNotEmpty(dto.getSphfwmc()), VmsDifferentialCode::getSphfwmc, dto.getSphfwmc())
                .likeRight(StringUtil.isNotEmpty(dto.getSphfwfljc()), VmsDifferentialCode::getSphfwfljc, dto.getSphfwfljc())
                .orderByDesc(VmsDifferentialCode::getCreateTime, VmsDifferentialCode::getId)
        );

        IPage<DifferentialCodePageVo> result = page.convert(item -> {
            DifferentialCodePageVo vo = new DifferentialCodePageVo();
            BeanUtils.copyBeanProp(vo, item);
            return vo;
        });
        return Result.OK(result);
    }

    @Override
    @Transactional
    public Result<Object> getDifferentialCodeByLq(TokenUser tokenUser) {
        // 先记录日志操作
        VmsDifferentialCodeRecord record = new VmsDifferentialCodeRecord();
        ArrayList<VmsDifferentialCode> list = new ArrayList<>();
        ArrayList<VmsDifferentialCodeRInfo> rList = new ArrayList<>();
        String deptCode = tokenUser.getDeptCode();
        String createUser = tokenUser.getUserCode();
        String createUsername = tokenUser.getUserName();
        Date date = new Date();

        BaseUserInfoParam baseUserInfoParam = new BaseUserInfoParam();
        baseUserInfoParam.setCreateUser(createUser);
        baseUserInfoParam.setDeptCode(deptCode);
        Result<QueryDifferentialTaxationVO> result = dmzApiClientService.queryDifferentialTaxCode(baseUserInfoParam, null);

        // 构建记录表
        record.setDeptCode(deptCode);
        record.setCreateUser(createUser);
        record.setCreateUsername(createUsername);
        record.setCreateTime(date);

        if (ResponseEnum.SUCCESS.getCode().equals(result.getCode())) {
            QueryDifferentialTaxationVO resultData = result.getData();
            log.info("{}调用DMZ查询差额征税编码信息成功", LOG_MSG);
            record.setLogCount(StringUtil.toString(resultData.getCount()));
            record.setOperateStatus(CommonConstant.STR_01);
            record.setOperateMsg(JSONObject.toJSONString(resultData));
            differentialCodeRecordService.save(record);

            // 构建实体信息
            List<QueryDifferentialTaxationVO.Cezsbm> cezsbmList = resultData.getCezsbmList();
            cezsbmList.forEach(item -> {
                VmsDifferentialCode vmsDifferentialCode = new VmsDifferentialCode();
                BeanUtils.copyBeanProp(vmsDifferentialCode, item);
                vmsDifferentialCode.setDeptCode(deptCode);
                vmsDifferentialCode.setCreateTime(date);
                vmsDifferentialCode.setCreateUser(createUser);
                vmsDifferentialCode.setCreateUsername(createUsername);
                list.add(vmsDifferentialCode);

                // 历史记录 列表数据
                VmsDifferentialCodeRInfo vmsDifferentialCodeRInfo = new VmsDifferentialCodeRInfo();
                BeanUtils.copyBeanProp(vmsDifferentialCodeRInfo, vmsDifferentialCode);
                vmsDifferentialCodeRInfo.setRid(record.getId());
                rList.add(vmsDifferentialCodeRInfo);
            });
            // 存入之前先删除原来数据
            deleteData(deptCode);
            // 保存新数据
            saveBatch(list);
            // 保存 历史记录 列表数据
            differentialCodeRInfoService.saveBatch(rList);
        } else {
            log.error("{}调用DMZ查询差额征税编码信息失败，原因：{}", LOG_MSG, result.getMessage());
            record.setOperateStatus(CommonConstant.STR_02);
            record.setOperateMsg(result.getMessage());
            differentialCodeRecordService.save(record);
            return Result.ERROR(result.getCode(), result.getMessage());
        }

        // 插入到记录表内
        return Result.OK_MSG(ResponseEnum.LEQI_SUCCESS.getMsg());
    }

    @Override
    public Result<IPage<DifferentialCodeLogPageVo>> logPage(DifferentialCodeLogPageDto dto) {
        IPage<DifferentialCodeLogPageVo> history = differentialCodeRecordService.getHistory(dto);
        return Result.OK(history);
    }

    @Override
    public Result<IPage<DifferentialCodePageVo>> logDetail(DifferentialCodeLogListDto dto) {
        Page<VmsDifferentialCodeRInfo> page = new Page<>(dto.getPageNo(), dto.getPageSize());
        LambdaQueryWrapper<VmsDifferentialCodeRInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(VmsDifferentialCodeRInfo::getRid, dto.getId());
        queryWrapper.orderByDesc(VmsDifferentialCodeRInfo::getCreateTime, VmsDifferentialCodeRInfo::getId);
        page = differentialCodeRInfoService.page(page, queryWrapper);
        IPage<DifferentialCodePageVo> result = page.convert(item -> {
            DifferentialCodePageVo vo = new DifferentialCodePageVo();
            BeanUtils.copyBeanProp(vo, item);
            return vo;
        });
        return Result.OK(result);
    }

    @Override
    public Result<Object> checkDifferentialCode(String sphfwssflhbbm, BigDecimal slv, String fppz, String cezslxdm, String deptCode) {
        // 查询税收分类编码表
        LambdaQueryWrapper<VmsClassifyCode> query = new LambdaQueryWrapper<>();
        query.eq(VmsClassifyCode::getSphfwssflhbbm, sphfwssflhbbm);
        query.eq(VmsClassifyCode::getDeptCode, deptCode);
        VmsClassifyCode vmsClassifyCode = vmsClassifyCodeService.getOne(query);
        if (vmsClassifyCode == null || !CommonConstant.STR_Y.equals(vmsClassifyCode.getCezs())) {
            return Result.ERROR(ResponseEnum.CEZSBM_NOT_FIND_ERROR);
        }

        // 查询差额征税编码表
        LambdaQueryWrapper<VmsDifferentialCode> query2 = new LambdaQueryWrapper<>();
        query2.eq(VmsDifferentialCode::getSphfwssflhbbm, sphfwssflhbbm);
        query2.eq(VmsDifferentialCode::getDeptCode, deptCode);
        VmsDifferentialCode differentialCode = getOne(query2);
        if (differentialCode == null) {
            return Result.ERROR(ResponseEnum.CEZSBM_NOT_FIND_ERROR);
        }

        /*
        选择 1100301010000000000 自来水商品编码、3040801010000000000 物业管理服务 商品编码开具
        差额征收方式，需要纳税人主附国标行业类别（行业代码为702或7020）是物业管理服务才能开具
        */
        // 获取行业代码
        VmsEnterpriseInfo enterpriseInfo = vmsEnterpriseInfoService.getInfoByRedis(deptCode);
        List<String> codeList = Arrays.asList("1100301010000000000", "3040801010000000000");
        if (codeList.contains(sphfwssflhbbm)) {
            if (enterpriseInfo != null && StringUtils.isNotBlank(enterpriseInfo.getHydm())) {
                if (!enterpriseInfo.getHydm().startsWith("702")) {
                    return Result.ERROR(ResponseEnum.CEZSBM_HYDM_ERROR);
                }
            } else {
                return Result.ERROR(ResponseEnum.CEZSBM_HYDM_ERROR);
            }
        }

        /*
        仅银行业金融机构（行业代码为662/663开头的货币银行服务及非货币银行服务机构）和金融
        资产管理公司（行业代码为6950的金融资产管理公司）中的增值税一般纳税人在“差额征税-差额开票”
        模式下选择以下商品编码时（5010102000000000000、5010199000000000000、5010202000000000000、
        5010299000000000000、5019900000000000000。5020000000000000000、5030000000000000000），
        允许使用下表中对应的税率（0.09）开票
        */
        List<String> codeList2 = Arrays.asList("5010102000000000000", "5010199000000000000", "5010202000000000000", "5010299000000000000",
                "5019900000000000000", "5020000000000000000", "5030000000000000000");
        if (codeList2.contains(sphfwssflhbbm) && new BigDecimal("0.09").compareTo(slv) == 0) {
            if (!CommonEnum.CEZS_02.getKey().equals(cezslxdm)
                    || enterpriseInfo == null
                    || StringUtils.isBlank(enterpriseInfo.getHydm())
                    || (!enterpriseInfo.getHydm().startsWith("662")
                        && !enterpriseInfo.getHydm().startsWith("663")
                        && !enterpriseInfo.getHydm().startsWith("6950"))) {
                return Result.ERROR(String.format(ResponseEnum.CEZSBM_HYDM_ERROR2.getMsg(), sphfwssflhbbm));
            }
        }

        /*
        所有的差额征收编码都可以开具“差额征税-全额开票”的普票；差额征收编码是否可以差额征税-差额开票、
        差额开票是否可以开专票、全额开票是否可以开专票根据差额征收编码表标志判断
        */
        // 校验全额开票
        if (CommonEnum.CEZS_01.getKey().equals(cezslxdm)) {
            // 校验全额开票是否可以开专票
            if (CommonEnum.INVOICE_TYPE_01.getKey().equals(fppz)) {
                if (!CommonConstant.STR_Y.equals(differentialCode.getQekpsfkykzp())) {
                    return Result.ERROR(ResponseEnum.CEZSBM_QEKP_ERROR);
                }
            }
        }
        // 校验差额开票
        if (CommonEnum.CEZS_02.getKey().equals(cezslxdm)) {
            // 校验差额开票是否可以开专票
            if (CommonEnum.INVOICE_TYPE_01.getKey().equals(fppz)) {
                if (!CommonConstant.STR_Y.equals(differentialCode.getCekpsfkykzp())) {
                    return Result.ERROR(ResponseEnum.CEZSBM_CEKP_ZP_ERROR);
                }
            }
            // 校验差额开票是否可以开普票
            if (CommonEnum.INVOICE_TYPE_02.getKey().equals(fppz)) {
                if (!CommonConstant.STR_Y.equals(differentialCode.getSfkycekp())) {
                    return Result.ERROR(ResponseEnum.CEZSBM_CEKP_PP_ERROR);
                }
            }
        }

        return Result.OK();
    }

    private void deleteData(String deptCode) {
        remove(new LambdaQueryWrapper<>(new VmsDifferentialCode()).eq(VmsDifferentialCode::getDeptCode, deptCode));
    }

}




